#include "voronoi.h"
#include "smart_print.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

Vertex* vertices = 0;

struct popen2 {
    pid_t child_pid;
    FILE* from_child;
    FILE* to_child;
};

int popen2(const char *cmdline, struct popen2 *childinfo) {
    pid_t p;
    int pipe_stdin[2], pipe_stdout[2];

    if(pipe(pipe_stdin)) return -1;
    if(pipe(pipe_stdout)) return -1;

    p = fork();
    if(p < 0) return p; /* Fork failed */
    if(p == 0) { /* child */
        close(pipe_stdin[1]);
        dup2(pipe_stdin[0], 0);
        close(pipe_stdout[0]);
        dup2(pipe_stdout[1], 1);
        execl("/bin/sh", "sh", "-c", cmdline, 0);
        perror("execl"); exit(1);
    }
    if (p < 0) {
        return -1;
    }
    childinfo->child_pid = p;
    childinfo->to_child = fdopen(pipe_stdin[1], "w");
    if (childinfo->to_child == NULL) {
        close(pipe_stdin[1]);
        close(pipe_stdout[0]);
        return -1;
    }
    childinfo->from_child = fdopen(pipe_stdout[0], "r");
    if (childinfo->from_child == NULL) {
        fclose(childinfo->to_child);
        close(pipe_stdout[0]);
        return -1;
    }
    return 0; 
}

void build_voronoi(const vector<double>& ps, vector<polygon>& res) {
    delete [] vertices;
    res.clear();

    struct popen2 ci;
    popen2("qhull/bin/qvoronoi o", &ci);
    fprintf(ci.to_child, "2 %d -3.0 -3.0 -3.0 4.0 4.0 4.0 4.0 -3.0 ", 4 + ps.size() / 2);
    for (int i = 0; i < ps.size() / 2; ++i) {
        fprintf(ci.to_child, "%lf %lf ", ps[2 * i], ps[2 * i + 1]);
    }
    fclose(ci.to_child);

    int dummy, points, polygons, count, v;
    float dummy2;
    fscanf(ci.from_child, "%d%d%d%d%f%f", &dummy, &points, &polygons, &dummy, &dummy2, &dummy2);
    vertices = new Vertex[--points];
    for (int i = 0; i < points; ++i) {
        fscanf(ci.from_child, "%f%f", &vertices[i].x, &vertices[i].y);
    }
    for (int i = 0; i < polygons; ++i) {
        bool b = true;
        polygon p;
        fscanf(ci.from_child, "%d", &count);
        for (int j = 0; j < count; ++j) {
            fscanf(ci.from_child, "%d", &v);
            if (v == 0) {
                b = false;
            }
            if (b) {
                p.push_back(v - 1);
            }
        }
        if (b) {
            res.push_back(p);
        }
    }
    fclose(ci.from_child);
}
